package com.ruoyi.project.pay;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.project.channel.businessRate.domain.BusinessRate;
import com.ruoyi.project.channel.channelOrder.domain.ChannelOrder;
import com.ruoyi.project.channel.payerBusinessInfo.domain.PayerBusinessInfo;
import com.ruoyi.project.channel.payerBusinessInfo.service.IPayerBusinessInfoService;
import com.ruoyi.project.channel.payerInfo.domain.PayerInfo;
import com.ruoyi.project.channel.payerInfo.service.IPayerInfoService;
import com.ruoyi.project.pay.vnet.Base64;
import com.ruoyi.project.pay.vnet.RQPayUtils;
import com.ruoyi.project.pay.vnet.RSAUtils;
import com.ruoyi.project.pay.vnet.SSLView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.net.ssl.HttpsURLConnection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;

/**
 * 对接DEMO
 *
 * @author lipo
 * @date 2018-12-27
 */
@Service
public class PayVnetServiceImpl {
    /**
     * 测试商户号
     */
//	public static final String TEST_MER = "A190419021347980";
//	/** 测试公钥 */
//	public static final String TEST_PUB_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDROvlVjMw5bo023YO5zrIaXFAJgSKTANdX0iDI8yYJvctcQcwT0KaTHv4C8b6vrcpTcH9AgXYAt0I5k5N4uCKnsFaHoJkmSGDLFTXG5S7lkbyQfu6nlvHhJtr0zV1d76NPdw4s69lt4S0TevUuJqH3auv22C1R8XioUrvQSPWs/wIDAQAB";
//	/** 测试私钥 */
//	public static final String TEST_PRI_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANE6+VWMzDlujTbdg7nOshpcUAmBIpMA11fSIMjzJgm9y1xBzBPQppMe/gLxvq+tylNwf0CBdgC3QjmTk3i4IqewVoegmSZIYMsVNcblLuWRvJB+7qeW8eEm2vTNXV3vo093Dizr2W3hLRN69S4mofdq6/bYLVHxeKhSu9BI9az/AgMBAAECgYEArvSCY4/9gZS4zoUCTg/RjAte/eOWlpfgedYChiYTy5eCAh4e2P7jGyiSPMIKsno/MfBi5/yZQNX8sYp+iTZn+o9jjrp4JJ2w4xGdjdq+quGeLZaGvZZSQ6VeSXxzC+Wy6Txf2+SQhbNelHOYBrMWfox9HUtX4UyOjI8U35ozwXECQQDtUr5CftIzus2LaK74mF6mIUpj1xq9lTkS5OfSdaLvqPKrLJ91OwtduHTDChLdCHsGm3fYFoe5PHm0gISP84LpAkEA4bJBWVMWDJ2nKS7wfIWu/Gs2iYrLVYU21tEecXWZyE33unJgJMcUy42o5/Kuq8+oX6UCHcxyDHlCv8QTxu6vpwJBAIhCRbLwFchVrMYqKKva8Bz6aDfCvTu0fbx3aRLRL+fiXNIjILqyV+hLi96f3gzCXcCBauHKrcqRCl+0mmf8LGECQQDfApjp31xZKOpEmloMYLfQOUwRSjCyl0fhqY5wQ+ipcMkI1P1FOeXFYHt2fWi04iKYJ17Y/OvwgV1ASUnVdoHfAkAengnu5bXwqi0YqjmuwSqveQFfV6fV+YqTIsMF6OohmqFMe/V6yXMWoe3XEAZNrx0O8d3IsO+E5Z9iZW/J5LA9";
//	/** 支付请求地址 */
//	public static final String PAY_URL = "https://api.v-pays.net";
//	/** 订单查询地址 */
//	public static final String QUERY_URL = "https://www.a-pay.vip/status/";
//	/** 测试回调地址 */
//	public static final String NORIFY_URL = "https://www.baidu.com";
    @Autowired
    private PayConfig payConfig;
    private static final Logger log = LoggerFactory.getLogger(PayVnetServiceImpl.class);
    @Autowired
    private IPayerInfoService payerInfoService;
    @Autowired
    private IPayerBusinessInfoService payerBusinessInfoService;

    // 测试
//    public static void main(String[] args) throws Exception {
//		pay();
//		query();
//    }


    /**
     * 异步回调模拟接收验签方法--也可以用实体类接收
     */
//    protected void doPost(HttpServletRequest request, HttpServletResponse response)
//            throws ServletException, IOException {
//        Map<String, String> params = new HashMap<String, String>();
//        Map requestParams = request.getParameterMap();
//        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
//            String name = (String) iter.next();
//            String[] values = (String[]) requestParams.get(name);
//            String valueStr = "";
//            for (int i = 0; i < values.length; i++) {
//                valueStr = (i == values.length - 1) ? valueStr + values[i]
//                        : valueStr + values[i] + ",";
//            }
//            params.put(name, valueStr);
//        }
//        log.info("【获取回调参数】" + params.toString());
//        //验签
//        String sign = params.get("sign");
////		if(checkSign(sign)){//验签成功
////			//TODO 业务处理
////		}else{
////			//TODO 验签失败 不处理业务
////		}
//    }


    /**
     * 查询请求DEMO
     * @throws Exception
     * @date 2018-12-27
     */
//	public static void query()throws Exception{
//		// 跳过SSL 验证
//		SSLView.trustAllHttpsCertificates();
//		HttpsURLConnection.setDefaultHostnameVerifier(new SSLView().hv);
//		// 请求参数拼接
//		Map<String, String> requestMap = new HashMap<String, String>();
//		requestMap.put("mno", TEST_MER);
//		requestMap.put("orderno", "20181227153004264");
//		requestMap.put("amount", "1000");
//		requestMap.put("sign", getSign(requestMap));
//		System.out.println("【请求参数】" + requestMap.toString());
//		// 发起请求
//		String result = RQPayUtils.sendPost(QUERY_URL, requestMap);
//		System.out.println("【返回信息】" + result);
//		/**
//		 * 返回示例：
//		 * 【返回信息】{"
//		 * code":"success","
//		 * msg":"请求查询订单交易信息","
//		 * data":{"
//		 * s_orderno":"2018122715301038297589570946","
//		 * m_orderno":"20181227153004264","
//		 * status":0,"
//		 * pt_id":1,"
//		 * addtime":"2018-12-27 15:30:10","
//		 * paytime":"","
//		 * paystatus":"未支付"}}
//		 */
//
//
//	}


    /**
     * 支付请求DEMO
     *
     * @throws Exception
     */
    public JSONObject pay(ChannelOrder channelOrder,BusinessRate businessRate){
        PayerInfo payerInfo = payerInfoService.selectPayerInfoById(businessRate.getPayerId());
        if (payerInfo == null) {
            log.error("setToJHNextOrder:找不到支付商");
            return null;
        }
        // 设置支付商id
        PayerBusinessInfo search = new PayerBusinessInfo();
        search.setPayerId(businessRate.getPayerId());
        search.setBusinessNo(businessRate.getPayerBusinessId());
        List<PayerBusinessInfo> payerBusinessInfos = payerBusinessInfoService.selectPayerBusinessInfoList(search);
        if (payerBusinessInfos.size() == 0) {
            log.error("setToJHNextOrder:找不到支付商商户");
            return null;
        }
        if (payerBusinessInfos.size() > 1) {
            log.error("setToJHNextOrder:找到多个支付商商户");
            return null;
        }

        // 跳过SSL 验证
        try{
            SSLView.trustAllHttpsCertificates();
        }catch (Exception error){
            log.error(error.getMessage(),error);
        }

        HttpsURLConnection.setDefaultHostnameVerifier(new SSLView().hv);
        // 请求参数拼接
        Map<String, String> requestMap = new HashMap<String, String>();
//        String orderNo =channelOrder.getPtOrderno();
//        System.out.println("请求订单号:" + orderNo);
        requestMap.put("mno", payerBusinessInfos.get(0).getBusinessNo());
        requestMap.put("orderno", channelOrder.getPtOrderno());
        requestMap.put("amount", (channelOrder.getAmount().multiply(BigDecimal.valueOf(100L)) + "").replace(".00","").replace(".0",""));// 单位分
        // 支付类型 1=支付宝 2=微信  3=网关 4=银联 5=百度钱包6=京东支付
        requestMap.put("pt_id", businessRate.getPayerPayType());
        // 应用场景 1=移动端 2=PC端
        requestMap.put("device", "1");
        // 签名
        requestMap.put("sign", getSign(requestMap, payerBusinessInfos.get(0).getApiKey().replaceAll("\r","").replaceAll("\n","")));
        // 除同步通知notify_url和异步通知async_notify_url无需加入参数
        String callbackUrl = payConfig.getPayCenterHost() + "/callback/vnet";
        requestMap.put("notify_url", callbackUrl);// 需要填写自己的同步通知URL
        requestMap.put("async_notify_url", callbackUrl);// 需要填写自己的异步通知URL

        log.info("【请求参数】" + requestMap.toString());
        // 发起请求
        String body = RQPayUtils.sendPost(payerInfo.getServiceUrl(), requestMap);
        log.info("【返回信息】" + body);
        JSONObject object = JSONObject.parseObject(body);
        String code = object.getString("code");
        if (!"success".equals(code)) {
            return object;
        }
        JSONObject data = object.getJSONObject("data");
        String _payUrl = data.getString("payurl");
        JSONObject result = new JSONObject();
        JSONObject payData = new JSONObject();
        payData.put("payUrl", _payUrl);
        payData.put("third", "true");
        result.put("data", payData);
        return result;
    }


    /**
     * 异步回调验签
     *
     * @param sign
     * @return
     * @date 2018-12-27
     */
    public boolean checkSign(String sign, String publicKey, String privateKey) {
        //公钥解密
        log.info("publicKey:"+publicKey);
        log.info("privateKey:"+privateKey);
        String str;
        boolean boo = false;
        try {
            str = new String(RSAUtils.decryptByPublicKey(com.ruoyi.project.pay.vnet.Base64.decode(sign), publicKey));
            log.info("公钥解密==" + str);
            //生成数字签名
            String qming = RSAUtils.sign(com.ruoyi.project.pay.vnet.Base64.decode(sign), privateKey);
            log.info("数字签名：" + qming);
            //验签名
            boo = RSAUtils.verify(com.ruoyi.project.pay.vnet.Base64.decode(sign), publicKey, qming);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return boo;
    }


//    public static void testMap() {
//		Map<String, String> paramReq = new HashMap<String, String>();
//		//商户号
//        paramReq.put("mno", "A190511215458040");
//		//订单号
//        paramReq.put("orderno", "0516165800604725277");
//        paramReq.put("amount",  "1100");
//		//指定为支付宝
//        paramReq.put("pt_id",  "1");
//		//指定为移动端
//        paramReq.put("device",  "1");
//         System.out.println(getSign(paramReq));
//    }

    public PrivateKey getPrivateKey(String key) {
        try {
            byte[] byteKey = com.ruoyi.project.pay.vnet.Base64.decode(key);
            PKCS8EncodedKeySpec x509EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(x509EncodedKeySpec);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 签名
     *
     * @param params
     * @return
     * @date 2018-12-27
     */
    public String getSign(Map<String, String> params, String privateKey) {
        TreeMap<String, String> param = new TreeMap<String, String>(params);
        String signInfo = "";
        for (String pkey : param.keySet()) {
            signInfo += pkey + "=" + param.get(pkey) + "&";
        }
        signInfo = signInfo.substring(0, signInfo.length() - 1);
        System.out.println("signInfo:" + signInfo);
        String sign = "";// 生成签名
        try {
            //私钥加密
            sign = Base64.encode(RSAUtils.encryptByPrivateKey(signInfo.getBytes("UTF-8"), privateKey));
            /**异步回调时 公钥解密--私钥生成数字签名---验签---返回true  则验签完成*/
//			//公钥解密
//			String str=new String(RSAUtils.decryptByPublicKey(Base64.decode(sign), TEST_PUB_KEY));
//			System.out.println("公钥解密=="+str);
//			
//			//生成数字签名
//			String qming=RSAUtils.sign(Base64.decode(sign), TEST_PRI_KEY);
//			System.out.println("数字签名："+qming);
//			
////			//验签名
//			boolean boo=RSAUtils.verify(Base64.decode(sign), TEST_PUB_KEY, qming);
//			System.out.println(boo);


        } catch (Exception e) {
            e.printStackTrace();
        }
        return sign;
    }


}
